package com.xc.pay.ali.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayObject;
import com.alipay.api.domain.BankcardExtInfo;
import com.alipay.api.domain.Participant;
import com.xc.pay.ali.constant.AliProperties;
import com.xc.pay.ali.enums.AliMethodEnum;
import com.xc.pay.ali.enums.PayeeInfoTypeEnum;
import com.xc.pay.ali.enums.ProductCodeEnum;
import com.xc.pay.ali.modal.VerifyPayParamModel;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.Objects;

/**
 * 支付宝 验证参数工具类
 *
 * @author rongrong
 * @date 2020/11/24
 */
@Slf4j
public class VerifyPayParamUtil {

  /**
   * 支付验证必要参数 不为空 totalAmount 金额不允许为空 并 0.01 < value < 100000000 outTradeNo 订单号 subject 标题
   *
   * @param param 支付宝model类的父类 通用接收
   * @param payType 支付类型
   * @throws AlipayApiException 异常
   */
  public static void verifyParam(AlipayObject param, AliMethodEnum payType)
      throws AlipayApiException {
    // 将阿里的Model参数copy进入自己的Model
    final VerifyPayParamModel paramModel =
        BeanUtil.copyProperties(param, VerifyPayParamModel.class);
    String totalAmount = paramModel.getTotalAmount();
    String outTradeNo = paramModel.getOutTradeNo();
    String subject = paramModel.getSubject();
    // 判断是哪种支付
    if (AliMethodEnum.TRADE_PAY.isTrue(payType)) {
      // 支付场景
      if (!Objects.nonNull(paramModel.getScene())) {
        throw new AlipayApiException("请设置支付场景");
      }
      if (!StrUtil.equalsAny(
          paramModel.getScene(), AliProperties.BAR_CODE, AliProperties.WAVE_CODE)) {
        throw new AlipayApiException("支付场景错误");
      }
      // 支付授权码  25~30开头的长度为16~24位的数字，实际字符串长度以开发者获取的付款码长度为准
      if (!Objects.nonNull(paramModel.getAuthCode())) {
        throw new AlipayApiException("支付授权码不允许为空");
      }
    } else if (AliMethodEnum.TRADE_CREATE.isTrue(payType)) {
      // 校验买家信息
      if (StrUtil.isAllBlank(paramModel.getBuyerId(), paramModel.getBuyerLogonId())) {
        throw new AlipayApiException("buyerId与buyerLogonId至少存在一个");
      }
    } else if (AliMethodEnum.FUND_TRANS_UNI_TRANSRER.isTrue(payType)) {
      totalAmount = paramModel.getTransAmount();
      outTradeNo = paramModel.getOutBizNo();
      subject = "xc";
      // 校验收款方信息
      final Participant payeeInfo = paramModel.getPayeeInfo();
      if (Objects.isNull(payeeInfo)) {
        throw new AlipayApiException("缺少收款方信息");
      }
      // 收款方类型
      final String identityType = payeeInfo.getIdentityType();
      if (StrUtil.isBlank(identityType)) {
        throw new AlipayApiException("缺少收款方标识类型identityType");
      }
      if (ProductCodeEnum.TRANS_BANKCARD_NO_PWD.isBankCard(paramModel.getProductCode())) {
        // 转账到银行卡
        if (!PayeeInfoTypeEnum.BANKCARD_NO.isBankCard(identityType)) {
          throw new AlipayApiException("请确认是否和product_code类型一致");
        }
        // 银行卡信息校验
        final BankcardExtInfo extInfo = payeeInfo.getBankcardExtInfo();
        if (extInfo == null) {
          throw new AlipayApiException("请确认是否已填写银行卡信息");
        }
        if (StrUtil.hasBlank(
            extInfo.getBankCode(), extInfo.getAccountType(), extInfo.getInstBranchName())) {
          throw new AlipayApiException("缺少银行卡信息");
        }
      } else {
        // 需确认product_code 和 identityType 类型要一致
        if (PayeeInfoTypeEnum.BANKCARD_NO.isBankCard(identityType)) {
          throw new AlipayApiException("请确认是否和product_code类型一致");
        }
      }
      // 收款方标识
      final String identity = payeeInfo.getIdentity();
      if (StrUtil.isBlank(identity)) {
        throw new AlipayApiException("缺少收款方标识");
      }
      // 收款方标识
      final String name = payeeInfo.getName();
      if (StrUtil.isBlank(name)) {
        throw new AlipayApiException("缺少收款方姓名");
      }
    }
    // 金额校验
    verifyTotalAmount(totalAmount);
    // 是否存在订单号  OutTradeNoUtil生成订单号工具类
    if (!Objects.nonNull(outTradeNo)) {
      throw new AlipayApiException("订单号不允许为空");
    }
    // 是否存在标题
    if (!Objects.nonNull(subject)) {
      throw new AlipayApiException("subject不允许为空");
    }
  }

  /**
   * 金额校验
   *
   * @param totalAmount 金额
   */
  public static void verifyTotalAmount(String totalAmount) throws AlipayApiException {
    // 参数校验
    if (Objects.isNull(totalAmount)) {
      throw new AlipayApiException("金额不允许为空");
    } else {
      final BigDecimal totalAmountBig = Convert.toBigDecimal(totalAmount);
      if (totalAmountBig.compareTo(AliProperties.LOWER) < 0
          || totalAmountBig.compareTo(AliProperties.UPPER) > 0) {
        throw new AlipayApiException("金额范围" + AliProperties.LOWER + "~" + AliProperties.UPPER);
      }
    }
  }
}
